public class PL0_Machine {
	static final int MAX_CODE_SIZE = 500;
	static final int STACK_SIZE = 500;

	PL0_Instruction[] codeArray = new PL0_Instruction[MAX_CODE_SIZE]; // code store
	int[] s = new int[STACK_SIZE]; // run-time stack, data store
	int program_counter, base_pointer, top_stack_pointer; // program-,base-,top-stack-registers
	PL0_Instruction instructionRegister = null; //	was i in original PL/0

	int cx = 0;

	// constructor and initializer
	public PL0_Machine() {
		top_stack_pointer = 0;
		base_pointer = 1;
		program_counter = 0;
		s[1] = 0;
		s[2] = 0;
		s[3] = 0;
	}

		public PL0_Instruction fetch() {
			return codeArray[program_counter];
		}
		public void interpret() {
			System.out.println("Start PL/0");
			for (;;) {
				instructionRegister = fetch();
				program_counter += 1;
				// with i do
				System.out.println("Function Code = " + instructionRegister.f);
				instructionRegister.f.perform(null);
				if (program_counter == 0) break;
			}
			System.out.println("End PL/0");
		}
	

	
	
	
	int base(int l) {
		int b1;
		b1 = base_pointer; // find base l levels down
		while (l > 0) {
			b1 = s[b1];
			l = l - 1;
		}
		;
		return b1;
	} // base



	/**
	 * to replace Pascal built-in function ord
	 * actually need to rethink
	 * two versions because I can't remember
	 */
	int ord(int argument) {
		if (argument > 0)
			return 1;
		else if (argument < 0)
			return -1;
		else
			return 0;
	}

	int ord(boolean argument) {
		if (argument)
			return 1;
		else
			return 0;
	}

	public void gen(PL0_Machine_Function f, int l, int a) {
		if (cx > MAX_CODE_SIZE) {
			System.out.print("Program too long");
			// in Pascal, goto 99
			// in Java, throw an exception, array will be out of bounds
		} else {
			// from Pascal
			//	code[cx].f= x; code[cx].l= y; code[cx].a= z;
			// in Java we just call the proper constructor
			codeArray[cx] = new PL0_Instruction(f, l, a);
			System.out.println("generated instruction for " + f + ", " + l
					+ ", " + a);
		};
		cx = cx + 1;
	}
	
	void listcode(int code_range) { // list code generated for this block
		for (int i = 0; i < code_range; i++) {
			PL0_Instruction instr = codeArray[i];
			System.out.println("Listing Code: " + i + " "
					+ instr.f.toString() + " " + instr.l + ", " + instr.a);
		}
	} // listcode

	/**
	 * Written for use in testing and debugging.
	 * Gives a little of the current machine state.
	 */
	public String toString() {
		String result = "Machine State:";
		result += " Top = " + top_stack_pointer;
		result += " Base = " + base_pointer;
		result += " Prog Counter = " + program_counter;
		result += " Code Index = " + cx;
		result += "\n                " + "                         ";
		result += " s[0] = " + s[0];
		result += " s[1] = " + s[1];
		result += " s[2] = " + s[2];
		result += " s[3] = " + s[3];
		result += " s[4] = " + s[4];
		result += " s[5] = " + s[5];

		return result;
	}

}